import React, { useRef, useState, useMemo, useCallback, useEffect } from 'react';
import { Config, Switch } from './subcomponents';
import ViewPicker from '@/components/viewpicker';
import type { DefaultView } from '@/components/viewpicker';
import { getActiveDefaultView } from '@/components/viewpicker/utils';
import { cloneDeep, isEmpty as _isEmpty, isEqual as _isEqual } from 'lodash';
import moment from 'moment';
import { Input, Button, Tooltip } from 'antd';
import classnames from 'classnames';
import { generateUuid } from '@/utils/utils';
import { getNormalInitSearchParams, getSchema, isViewInViews, getDefaultParams, checkViewHasAutoSearch } from './utils';
import styles from './index.less';
import type { View, UiConfigProps, SmartSearchLocalFilter } from '../searchform/interface';
import { getViewsApi, updateViewsApi } from './service';
import SearchForm from '../searchform';
import { useLocalStorage, getValues, resolveValue, getOrderInfo } from '../searchform/utils';

import type {
  SmartSearchSchema,
  SmartSearchCompatibilityModeSchema,
  OnSearch,
  OnSimpleSearch,
  SmartSearchRef,
  Multiple,
  CustomComponent,
  SmartSearchProps,
  SaveViewProps,
} from './type';
import { CONFIG_MODAL_SIZE, TRANSFER_CONFIG_MODAL_SIZE } from './constant';

// 存入localstorage的前缀
const STORAGE_PREFIX = 'smart_search_';
const STORAGE_PREFIX_FILTER = `${STORAGE_PREFIX}filter:`;
const DEFAULT_VIEW_PREFIX_FILTER = `${STORAGE_PREFIX}defaultView:`;
const VIEW_VERSION_FORMAT = 'YYYY-MM-DD HH:mm:SSSS';

// 搜索的默认设置
const INIT_UI_CONFIG: UiConfigProps = {
  searchType: 'click',
  searchAfterReset: true,
};

const SmartSearch = React.forwardRef(function SmartSearch(props: SmartSearchProps, ref: any) {
  const {
    searchPanelId = '',
    userId = '',
    title,
    onSearch,
    configModalSize = {},
    onSizeChange,
    schema,
    pageInfo,
    totalCount,
    hidePrintBtn = true,
    mode = 'simple',
    singleView = false,
    placeholder = tr('请输入查询内容'),
    onSimpleSearch,
    extra,
    isCompatibilityMode = false,
    customComponents = [],
    uiSchema = {},
    showSplitLine = true,
    onViewChange,
    initView,
    initParams = [],
    onValueChange,
    fieldTransfer = false,
    hideOrderField = false,
    loading,
    multiple,
    searchAfterReset,
    showDisplayConfig = false,
    paramsModeOnViewChange = 'initParams',
    filterAutoSearch = true,
    companyViewAuth = 'write',
    isCustomParams,
    isAutoSearch,
    ...restSearchFormProps
  } = props;

  const {
    supportFilterFields, // 是否支持筛选字段
    supportOrderFields = [], // 是否支持排序字段
    systemViews = [], // 系统视图
    systemFilters = [], // 系统参数
  } = schema;

  // 默认活跃的视图
  const defaultActiveView = !_isEmpty(initView)
    ? initView
    : !!systemViews?.length
    ? { ...systemViews[0], isSystem: true }
    : {};

  const defaultActiveMode = isCompatibilityMode || mode === 'advancedOnly' ? 'advanced' : mode;

  // 筛选参数
  const [filters, setFilters] = useLocalStorage<SmartSearchLocalFilter>(
    `${STORAGE_PREFIX_FILTER}${searchPanelId}${userId}`,
    {},
  );
  // 默认视图设置
  const [defaultView, setDefaultView] = useLocalStorage<DefaultView>(
    `${DEFAULT_VIEW_PREFIX_FILTER}${searchPanelId}${userId}`,
    {},
  );
  // 自定义视图设置
  const [customViews, setCustomViews] = useState<View[]>([]);
  // 共享视图设置
  const [companyViews, setCompanyViews] = useState<View[]>([]);
  // 活跃视图
  const [activeView, setActiveView] = useState<View>(defaultActiveView);
  // 加载laoding
  const [fetchLoading, setFetchLoading] = useState(false);
  // 视图是否加载完成
  const [viewLoaded, setViewLoad] = useState(false);
  // 是否保存完成
  const [saveLoading, setSaveLoading] = useState(false);
  // 保存为?
  const [saveAsLoading, setSaveAsLoading] = useState(false);
  // 重命名?
  const [renameLoading, setRenameLoading] = useState(false);
  // 改变视图?
  const [updateViewLoading, setUpdateViewLoading] = useState(false);
  // 动态模型
  const [activeMode, setActiveMode] = useState(defaultActiveMode);
  const [searchKeyword, setSearchKeyword] = useState('');
  const [isSimpleInputFocus, setIsSimpleInputFocus] = useState(false);
  const [currentSystemViews, setCurrentSystemViews] = useState(systemViews);
  const [configVisible, setConfigVisible] = useState(false);

  const activeModeRef = useRef(defaultActiveMode);
  const simpleSearchRef = useRef({} as any);
  const pageInfoRef = useRef(pageInfo);

  const configModalSize_ = useMemo(() => {
    let res = configModalSize;
    if (_isEmpty(configModalSize)) {
      res = fieldTransfer ? TRANSFER_CONFIG_MODAL_SIZE : CONFIG_MODAL_SIZE;
    }
    return res;
  }, [configModalSize, fieldTransfer]);

  // 记录最新的 filterItems（类似于initParams） 状态
  const latestFilterItemsRef = useRef({});

  const {
    panelConfig: { searchFields, uiConfig = INIT_UI_CONFIG },
  } = activeView;

  // searchForm schema 与 默认参数
  const [searchFormSchema, defaultParams, formOrder] = useMemo(() => {
    const [formSchema, oderKeys] = getSchema(supportFilterFields, searchFields, { multiple, customComponents });
    const defaultParams = getDefaultParams(formSchema);
    return [formSchema, defaultParams, oderKeys];
  }, [supportFilterFields, searchFields, customComponents, multiple]);

  const [currentInitParams, setCurrentInitParams] = useState(() => {
    return {};
  });

  const uiSchema_ = {
    ...uiSchema,
    'form:orders': formOrder,
  };

  const [autoSearch, autoSearchWait] = useMemo(() => {
    const { searchType, autoSearchWait = 1 } = uiConfig;
    const autoSearch = ['auto', 'autoNoDelay'].includes(searchType);
    let autoSearchWait_ = typeof autoSearchWait === 'number' ? autoSearchWait * 1000 : 1000;
    if (searchType === 'autoNoDelay') {
      autoSearchWait_ = 0;
    }
    return [autoSearch, autoSearchWait_];
  }, [uiConfig]);

  // 改变当前视图
  const changeActiveView = useCallback(
    (view: View, isInit = false) => {
      const {
        panelConfig: { uiConfig },
      } = view;
      if (!uiConfig) {
        view.panelConfig.uiConfig = INIT_UI_CONFIG;
      } else {
        view.panelConfig.uiConfig = {
          ...INIT_UI_CONFIG,
          ...uiConfig,
        };
      }
      setActiveView(view);
      onViewChange && onViewChange(view);
      if (!isInit) {
        switch (paramsModeOnViewChange) {
          case 'clear':
            setCurrentInitParams({});
            break;
          case 'initParams':
            setCurrentInitParams(getValues(initParams, searchFormSchema, isCompatibilityMode));
            break;
          case 'latest':
            setCurrentInitParams(getValues(latestFilterItemsRef.current, searchFormSchema, isCompatibilityMode));
            break;
        }
      }
    },
    [onViewChange, paramsModeOnViewChange, searchFormSchema, initParams, isCompatibilityMode],
  );

  // 获取自定义和企业视图列表
  const getCustomAndCompanyViews = useCallback(async () => {
    setFetchLoading(true);
    const localDataString = localStorage.getItem(`${DEFAULT_VIEW_PREFIX_FILTER}${searchPanelId}${userId}`);
    const defaultView: DefaultView = localDataString ? JSON.parse(localDataString) : {};
    // 自定义
    const tempCustomViews = await getViewsApi({
      dataId: searchPanelId,
      dataType: 'CustomView',
    });
    // 企业
    const tempCompanyViews = ['write', 'read'].includes(companyViewAuth)
      ? await getViewsApi({
          dataId: searchPanelId,
          dataType: 'CompanyView',
        })
      : [];
    const tempSystemViews: any[] = [...currentSystemViews];
    let initParams_;
    let activeDefaultView = undefined;
    if (!_isEmpty(initView)) {
      // 判断传入的初始视图是否某个全字段
      activeDefaultView = isViewInViews(tempSystemViews, initView, 'system');
      // 判断传入的初始视图是否某个自定义视图
      if (!activeDefaultView) {
        activeDefaultView = isViewInViews(tempCustomViews, initView, 'custom');
      }
      // 如果初始视图不在自定义视图中，则将其加入到全字段中
      if (!activeDefaultView) {
        const tempView = {
          ...initView,
          isSystem: true,
        };
        tempSystemViews.push(tempView);
        activeDefaultView = tempView;
      }
      initParams_ = getValues(initParams, searchFormSchema, isCompatibilityMode);
      setCurrentInitParams(initParams_);
    }

    // 单视图模式
    if (singleView && !!tempCustomViews.length) {
      activeDefaultView = tempCustomViews[0];
    }

    if (!activeDefaultView) {
      activeDefaultView = getActiveDefaultView({
        systemViews: tempSystemViews,
        companyViews: tempCompanyViews,
        customViews: tempCustomViews,
        defaultView,
      });
    }

    const extraProps: any = {};
    // 不是兼容模式添加排序字段
    if (!isCompatibilityMode) {
      extraProps.orderList = getOrderInfo(activeDefaultView.panelConfig.orderFields || [], isCompatibilityMode);
    }
    // 初始视图与初始查询参数都不为空
    if (!_isEmpty(initView) && !_isEmpty(initParams_)) {
      extraProps[isCompatibilityMode ? 'filterInfo' : 'whereList'] = resolveValue({
        params: initParams_,
        schema: searchFormSchema,
        type: 'search',
        isNormalSearch: false,
        isCompatibilityMode,
      });
    } else {
      let resParams = getNormalInitSearchParams(activeDefaultView.panelConfig.searchFields, isCompatibilityMode);
      if (!_isEmpty(defaultParams)) {
        const defaultParams_ = resolveValue({
          params: getValues(defaultParams, searchFormSchema, isCompatibilityMode),
          schema: searchFormSchema,
          type: 'search',
          isNormalSearch: false,
          isCompatibilityMode,
        });
        resParams = isCompatibilityMode ? { ...resParams, ...defaultParams_ } : [...resParams, ...defaultParams_];
      }
      extraProps[isCompatibilityMode ? 'filterInfo' : 'whereList'] = resParams;
    }

    // 这里需要根据条件来确定是否需要触发首次查询
    // 如果当前视图中存在筛选器开启了自动查询，那么这里不触发查询，否则触发查询
    const autoSearch = checkViewHasAutoSearch(activeDefaultView, filters);
    if (!autoSearch && filterAutoSearch) {
      // 初始查询
      onSearch && onSearch({ ...extraProps, pageInfo }, true, initParams);
    }

    if (isAutoSearch) {
      onSearch && onSearch({ filterInfo: initParams });
    }
    // 更新状态
    setViewLoad(true);
    changeActiveView(cloneDeep(activeDefaultView), true);
    setCustomViews(tempCustomViews);
    setCompanyViews(tempCompanyViews);
    setCurrentSystemViews(tempSystemViews);
    setFetchLoading(false);
  }, [
    searchPanelId,
    changeActiveView,
    companyViewAuth,
    currentSystemViews,
    defaultParams,
    filterAutoSearch,
    filters,
    initParams,
    initView,
    isAutoSearch,
    isCompatibilityMode,
    onSearch,
    pageInfo,
    searchFormSchema,
    singleView,
    userId,
  ]);

  // 调接口更新视图
  const viewSaveImpl = useCallback(
    async (props: SaveViewProps) => {
      const { type, views, hideModal, clearFilterView, operateView, defaultView, viewType } = props;
      let tempClearFilterView = clearFilterView;
      let saveLoadngFunc: () => void | undefined;
      const isCustom = viewType !== 'company';
      switch (type) {
        case 'save':
          saveLoadngFunc = setSaveLoading;
          break;
        case 'saveAs':
          saveLoadngFunc = setSaveAsLoading;
          break;
        case 'delete':
          saveLoadngFunc = setUpdateViewLoading;
          tempClearFilterView = operateView;
          break;
        case 'rename':
          saveLoadngFunc = setRenameLoading;
          break;
        default:
          break;
      }
      saveLoadngFunc && saveLoadngFunc(true);
      try {
        await updateViewsApi({
          dataId: searchPanelId,
          dataType: isCustom ? 'CustomView' : 'CompanyView',
          views,
        });

        // 更新组件状态中的个人视图或者共享视图
        (isCustom ? setCustomViews : setCompanyViews)(views);
        // 清除相关联筛选器
        if (tempClearFilterView) {
          const { viewId, version } = tempClearFilterView;
          const newFilters = { ...filters };
          delete newFilters[viewId + '|' + version];
          setFilters(newFilters);
        }
        // 当前视图
        if (operateView && operateView.viewId === activeView.viewId) {
          setActiveView(operateView);
        }
        hideModal && hideModal();
        // 默认视图
        if (defaultView) {
          setDefaultView(defaultView);
          setActiveView(views.filter((item) => item.viewId === defaultView.viewId)[0]);
        }
      } catch (error) {
      } finally {
        saveLoadngFunc && saveLoadngFunc(false);
      }
    },
    [activeView, filters, searchPanelId, setDefaultView, setFilters],
  );

  // 某个视图更新
  const onViewSave = useCallback(
    (view: View, hideModal) => {
      let isNeedClearFilter = false;
      let operateView;
      const newCustomViews = customViews.map((item) => {
        const { viewId } = item;
        let tempView = item;
        if (viewId === view.viewId && !_isEqual(view, item)) {
          tempView = view;
          if (!_isEqual(view.panelConfig.searchFields, item.panelConfig.searchFields)) {
            tempView.version = moment().format(VIEW_VERSION_FORMAT);
            isNeedClearFilter = true;
          }
          if (_isEqual(view.viewId, activeView.viewId)) {
            operateView = tempView;
          }
        }
        return {
          ...tempView,
        };
      });
      if (_isEqual(newCustomViews, customViews)) {
        hideModal && hideModal();
      } else {
        viewSaveImpl({
          views: newCustomViews,
          type: 'save',
          hideModal,
          clearFilterView: isNeedClearFilter ? view : undefined,
          operateView,
          viewType: view?.viewType == 'company' ? 'company' : 'custom',
        });
      }
    },
    [customViews, activeView, viewSaveImpl],
  );

  // 单视图的视图更新
  const onSingleViewSave = useCallback(
    (view: View, hideModal) => {
      const viewId = generateUuid(32, 16);
      viewSaveImpl({
        views: [{ ...view, viewId }],
        type: 'save',
        hideModal,
        clearFilterView: activeView,
        operateView: view,
        defaultView: { type: 'custom', viewId },
        viewType: 'custom',
      });
    },
    [activeView, viewSaveImpl],
  );

  // 另存视图
  const onViewSaveAs = useCallback(
    (data, hideModal) => {
      let newViews: View[] = [];
      const {
        values: { name, isDefault, type },
        searchFields,
        orderFields,
        uiConfig = INIT_UI_CONFIG,
      } = data;
      const newView: View = {
        viewId: generateUuid(32, 16),
        name,
        version: moment().format(VIEW_VERSION_FORMAT),
        panelConfig: {
          searchFields,
          orderFields,
          uiConfig,
        },
        viewType: type,
      };

      // 这里需要根据视图类型来判断更新的是哪个视图
      newViews = (type === 'company' ? companyViews : customViews).map((item) => {
        return {
          ...item,
        };
      });

      newViews.push(newView);

      viewSaveImpl({
        views: newViews,
        type: 'saveAs',
        hideModal,
        operateView: newView,
        defaultView: isDefault
          ? {
              type,
              viewId: newView.viewId,
            }
          : undefined,
        viewType: type,
      });
    },
    [customViews, companyViews, viewSaveImpl],
  );

  const activeModeUpdate = useCallback(() => {
    setActiveMode(activeMode === 'simple' ? 'advanced' : 'simple');
    activeModeRef.current = activeMode === 'simple' ? 'advanced' : 'simple';
  }, [activeMode]);

  const simpleSearch = useCallback(
    (page?: number | boolean, pageSize?: number) => {
      let newPageInfo = typeof page === 'boolean' ? pageInfo : { ...pageInfo, beginIndex: 0 };
      if (typeof page === 'number' && typeof pageSize === 'number') {
        newPageInfo = {
          pageSize,
          beginIndex: (page - 1) * pageSize,
        };
        pageInfoRef.current = newPageInfo;
      }
      onSimpleSearch &&
        onSimpleSearch({
          searchKeyword: searchKeyword,
          pageInfo: newPageInfo,
        });
    },
    [searchKeyword, pageInfo, onSimpleSearch],
  );

  const onSearchKeywordChange = useCallback((e) => {
    const value = e.target.value;
    setSearchKeyword(value);
  }, []);

  // 自定义onValueChange
  const currentOnValueChange = useCallback(
    (value: any, filterValue: any) => {
      onValueChange?.(value, filterValue);
      latestFilterItemsRef.current = value;
    },
    [onValueChange],
  );

  useMemo(() => {
    simpleSearchRef.current = simpleSearch;
  }, [simpleSearch]);

  useMemo(() => {
    if (activeModeRef.current === 'simple' && !_isEqual(pageInfo, pageInfoRef.current)) {
      pageInfoRef.current = pageInfo;
      const func = simpleSearchRef.current;
      // 标识这是外部改变了分页，无需将beginIndex设置为0
      func && func(true);
    }
  }, [pageInfo]);

  const noConfigViews = useMemo(() => {
    return (
      <ViewPicker
        viewName={activeView.name}
        viewId={activeView.viewId}
        defaultView={defaultView}
        customViews={customViews}
        companyViews={companyViews}
        systemViews={currentSystemViews}
        switchActiveView={changeActiveView}
        updateView={viewSaveImpl}
        renameLoading={renameLoading}
        loading={updateViewLoading}
        splitLine={true}
        onDefaultViewChange={setDefaultView}
      />
    );
  }, [
    activeView.name,
    customViews,
    currentSystemViews,
    renameLoading,
    updateViewLoading,
    defaultView,
    viewSaveImpl,
    changeActiveView,
    companyViews,
    activeView.viewId,
    setDefaultView,
  ]);

  const titleRef = useRef(null);
  const views = useMemo(() => {
    return (
      <ViewPicker
        viewName={activeView.name}
        viewId={activeView.viewId}
        defaultView={defaultView}
        customViews={customViews}
        companyViews={companyViews}
        systemViews={currentSystemViews}
        switchActiveView={changeActiveView}
        updateView={viewSaveImpl}
        renameLoading={renameLoading}
        loading={updateViewLoading}
        splitLine={showSplitLine}
        onDefaultViewChange={setDefaultView}
        config={
          <Tooltip title={tr('配置')}>
            <Button size="small" icon="setting" onClick={() => setConfigVisible(true)} />
          </Tooltip>
        }
        getPopupContainer={() => titleRef.current || document.body}
      />
    );
  }, [
    activeView.name,
    customViews,
    currentSystemViews,
    renameLoading,
    updateViewLoading,
    defaultView,
    viewSaveImpl,
    showSplitLine,
    titleRef,
    changeActiveView,
    companyViews,
    activeView.viewId,
    setDefaultView,
  ]);

  const title_ = useMemo(() => {
    return (
      <div ref={titleRef}>
        {title}
        {isCompatibilityMode || mode === 'advancedOnly' || singleView ? null : (
          <div className={styles.queryBtn} onClick={activeModeUpdate}>
            {tr(activeMode === 'simple' ? '切换为高级查询视图' : '切换为简单查询视图')}
          </div>
        )}
        {!singleView && activeMode === 'advanced' && views}
        {singleView && (
          <span className={classnames(styles.singleViewConfig, { [styles.singleViewConfigSplitLine]: showSplitLine })}>
            <Tooltip title={tr('配置')}>
              <Button icon="setting" size="small" onClick={() => setConfigVisible(true)} />
            </Tooltip>
          </span>
        )}
      </div>
    );
  }, [title, views, activeMode, activeModeUpdate, singleView, isCompatibilityMode, mode, showSplitLine]);

  const simpleSearchInputFocusStatusChange = useCallback((res: boolean) => {
    setIsSimpleInputFocus(res);
  }, []);

  // 自定义组件列表
  const customComponents_ = useMemo(() => {
    return [
      ...customComponents,
      {
        name: 'SmartSearchSwitch',
        component: Switch,
      },
    ];
  }, [customComponents]);

  useEffect(() => {
    getCustomAndCompanyViews();
  }, []);

  useEffect(() => {
    if (activeModeRef.current === 'simple' && ref) {
      ref.current = {
        reset: () => setSearchKeyword(''),
        search: simpleSearchRef.current,
      };
    }
  });

  return (
    <>
      <SearchForm
        searchKey={searchPanelId + userId}
        ref={ref}
        title={title_}
        schema={searchFormSchema}
        activeView={activeView}
        customFilters={filters}
        onCustomFiltersChange={setFilters}
        systemFilters={systemFilters}
        onSmartSearch={onSearch}
        pageInfo={pageInfo}
        totalCount={totalCount}
        extra={<>{extra}</>}
        customComponents={customComponents_}
        isCompatibilityMode={isCompatibilityMode}
        showCustomBody={activeMode === 'simple'}
        customBody={
          <Input.Search
            size="small"
            className={classnames('margin10', [styles['simple-search-input']], {
              [styles['simple-search-input-focus']]: isSimpleInputFocus,
            })}
            value={searchKeyword}
            placeholder={placeholder}
            enterButton
            style={{ width: '50%' }}
            onChange={onSearchKeywordChange}
            onSearch={simpleSearch}
            onFocus={simpleSearchInputFocusStatusChange.bind(null, true)}
            onBlur={simpleSearchInputFocusStatusChange.bind(null, false)}
          />
        }
        uiSchema={uiSchema_}
        hidePrintBtn={hidePrintBtn}
        onSizeChange={onSizeChange}
        autoSearch={autoSearch}
        autoSearchWait={autoSearchWait}
        initParams={isCustomParams ? initParams : currentInitParams}
        onValueChange={currentOnValueChange}
        searchAfterReset={searchAfterReset}
        loading={loading || fetchLoading}
        viewLoaded={viewLoaded}
        filterAutoSearch={filterAutoSearch}
        {...restSearchFormProps}
      />
      <div style={{ height: 0 }}>
        <Config
          singleView={singleView}
          visible={configVisible}
          setVisible={setConfigVisible}
          activeView={activeView}
          viewSelector={noConfigViews}
          supportOrderFields={supportOrderFields}
          supportFilterFields={supportFilterFields}
          configModalSize={configModalSize_}
          onSave={onViewSave}
          loading={saveLoading}
          onSaveAs={onViewSaveAs}
          saveAsLoading={saveAsLoading}
          isCompatibilityMode={isCompatibilityMode}
          fieldTransfer={fieldTransfer || isCompatibilityMode}
          hideOrderField={hideOrderField || isCompatibilityMode}
          onSingleViewSave={onSingleViewSave}
          systemViews={currentSystemViews}
          companyViews={companyViews}
          customViews={customViews}
          showDisplayConfig={showDisplayConfig}
          companyViewAuth={companyViewAuth}
          uiSchema={uiSchema_}
        />
      </div>
    </>
  );
});

SmartSearch.displayName = 'SmartSearch';

// 统一一个文件导出， 方便其他地方统一导入
export type {
  SmartSearchSchema,
  SmartSearchCompatibilityModeSchema,
  OnSearch,
  OnSimpleSearch,
  SmartSearchRef,
  Multiple,
  CustomComponent,
  SmartSearchProps,
  SaveViewProps,
};

export { STORAGE_PREFIX };

export default SmartSearch;
